from ...pao_python.pao.service.data.mongo_db import MongoService, MongoFilter, C, N, F, as_date
from ...service.buss_pub.bill_manage import BillManageService, OperationType, Status, TypeId
from ...service.mongo_bill_service import MongoBillFilter
from ...service.welfare_institution.accommodation_process import AccommodationProcess
from ...service.common import get_info, get_current_user_id, operation_result
from ...service.app.my_order import OrderStatus, RecordStatus
from ...service.buss_mis.service_operation import ServiceOperationService
from ...pao_python.pao.remote import JsonRpc2Error
from ...pao_python.pao.data import string_to_date_only, dataframe_to_list
import pandas as pd
from ...service.welfare_institution.accommodation_process import CheckInStatus


class Hydropower(MongoService):

    def __init__(self, db_addr, db_port, db_name, db_user, db_pwd, inital_password, session):
        self.db_addr = db_addr
        self.db_port = db_port
        self.db_name = db_name
        self.db_user = db_user
        self.db_pwd = db_pwd
        self.inital_password = inital_password
        self.session = session
        self.bill_manage_server = BillManageService(
            self.db_addr, self.db_port, self.db_name, self.db_user, self.db_pwd, self.inital_password, self.session)
        self.accommodation_process = AccommodationProcess(
            db_addr, db_port, db_name, db_user, db_pwd, inital_password, session)
        self.service_operation_func = ServiceOperationService(
            db_addr, db_port, db_name, db_user, db_pwd, inital_password, session)

    def get_hydropower_list(self, org_list, condition, page, count):
        if 'start_date' in list(condition.keys()):
            condition['start_date_s'] = condition['start_date'][0]
            condition['end_date_s'] = condition['start_date'][1]
        if 'end_date' in list(condition.keys()):
            condition['start_date_e'] = condition['end_date'][0]
            condition['end_date_e'] = condition['end_date'][1]
        keys = ['id', 'hotel_id', 'start_date_s',
                'end_date_s', 'start_date_e', 'end_date_e']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.lookup_bill('PT_Hotel_Zone', 'hotel_id', 'id', 'hotel') \
               .match_bill(
            (C('id') == values['id'])
            & (C('start_date') >= as_date(values['start_date_s']))
            & (C('start_date') <= as_date(values['end_date_s']))
            & (C('end_date') >= as_date(values['start_date_e']))
            & (C('end_date') <= as_date(values['end_date_e']))
            & (C('hotel_id') == values['hotel_id'])
            & (C('organization_id').inner(org_list)))\
            .add_fields({'hotel_name': '$hotel.zone_name'})\
            .project({'_id': 0, 'hotel._id': 0})
        res = self.page_query(_filter, 'IEC_Hydropower', page, count)
        return res

    def update_hydropower(self, condition, isImport=False):
        recode = []
        # 获取当前服务人员id
        servicer_id = get_current_user_id(self.session)
        # 默认编辑状态
        flag = OperationType.update.value
        # 格式化时间
        condition.update(start_date=string_to_date_only(condition['start_date'].split(
            'T')[0]), end_date=string_to_date_only(condition['end_date'].split('T')[0]))
        date_recode = {'start_date': condition['start_date'], 'end_date': condition['end_date'],
                       'status': RecordStatus.service_completed.value, 'servicer_id': servicer_id}
        # 获取该房间的长者以及入住id,用于生成服务记录
        _filter = MongoBillFilter()
        _filter.match_bill((C('area_id') == condition['hotel_id']) & (C('residents_id') != '')) \
               .inner_join_bill('IEC_Check_In', 'residents_id', 'user_id', 'check') \
               .match_bill(C('check.state') == '居住中')\
               .lookup_bill('PT_Accommodation_Record', 'residents_id', 'residents_id', 'recode') \
               .project({'_id': 0, 'check._id': 0})

        res = self.query(_filter, 'PT_Bed')
        num = len(res)
        bill_id = False
        if num:
            # 获取该区域所有人这段时间的住宿天数，水电总数情况
            options = self.__get_accommodation_days(
                res, condition, {'count': num})
            # 生成水电费服务记录参数
            for option in options:
                # 用水量
                if option.get('water_number'):
                    params_water = option['water_number']
                    params_water_recode = self.accommodation_process.get_item_info(
                        *params_water)
                    for x in params_water_recode:
                        new_x = dict(x, **date_recode)
                        service_water_recode = self.service_operation_func.add_service_record(
                            new_x['order_id'], new_x['service_product_id'], '0', other=new_x, is_update=option['recode_id'])
                        service_water_recode['type'] = '水费'
                        recode.append(service_water_recode)
                # 用电量
                if option.get('electricity_number'):
                    params_electricity = option['electricity_number']
                    params_electricity_recode = self.accommodation_process.get_item_info(
                        *params_electricity)
                    for y in params_electricity_recode:
                        new_y = dict(y, **date_recode)
                        service_electricity_recode = self.service_operation_func.add_service_record(
                            new_y['order_id'], new_y['service_product_id'], '0', other=new_y, is_update=option['recode_id'])
                        service_electricity_recode['type'] = '电费'
                        recode.append(service_electricity_recode)
            table_name = ['IEC_Hydropower', 'PT_Service_Record']
            if not 'id' in condition.keys():  # 新增
                flag = OperationType.add.value
                recode_order_ids = []
                for x in range(0, len(recode)):
                    condition = get_info(condition, self.session)
                    recode[x] = get_info(recode[x], self.session)  # 添加记录id
                    recode_order_ids.append(
                        {
                            'recode_id': recode[x]['id'],
                            'order_id': recode[x]['order_id'],
                            'type': recode[x]['type']
                        }
                    )
                    del recode[x]['type']
                # 水电表保存记录id
                condition.update(recode_order_ids=recode_order_ids)
            if isImport:
                pass
            else:
                bill_id = self.bill_manage_server.add_bill(flag, TypeId.hydropower.value, [
                                                           [condition], recode], table_name)
                if not bill_id:
                    raise JsonRpc2Error(500, '抄表记录失败，请检查该床位。')
                return operation_result(bill_id)

    def __get_accommodation_days(self, result, condition, params):
        '''获取某个入住订单下，某时间段内的住宿天数，用水/电情况'''
        options = []
        start_con = condition['start_date']
        end_con = condition['end_date']
        for res in result:
            days = 0
            for recode in res['recode']:
                start = recode['checkin_date']
                end = ''
                if 'checkout_date' in recode.keys():
                    end = recode['checkout_date']
                if 'fictitious_checkout_date' in recode.keys():
                    end = recode['fictitious_checkout_date']
                if end == '':  # 进入之后未离开
                    if start > end_con:  # 住宿记录不在统计时间范围内
                        days = days + 0
                    elif start < start_con:  # 进入时间在于统计时间，统计的住宿天数为查询条件的时间段
                        days = days + (end_con - start_con).days + 1
                    elif start_con < start and start > end_con:
                        days = days + (end_con - start).days + 1
                else:
                    if end < start_con or start > end_con:
                        days = days + 0
                    elif start >= start_con and end <= end_con:
                        days = days + (end - start).days + 1
                    elif start < start_con and end < end_con:
                        days = days + (end - start_con).days + 1
                    elif start < start_con and end > end_con:
                        days = days + (end_con - start_con).days + 1
                    elif start > start_con and end > end_con:
                        days = days + (end_con - start).days + 1
            if days == 0:
                days = (end_con - start_con).days + 1
            order_id = res['check']['order_id']
            # recode_id = self.__get_order_recode_id(condition,order_id)
            if condition.get('water_number'):
                options.append({
                    'order_id': order_id,
                    'recode_id': self.__get_order_recode_id(condition, order_id, '水费'),
                    'start_date': condition['start_date'],
                    'end_date': condition['end_date'],
                    'water_number': [
                        '水费',
                        order_id, {
                            '实际发生天数': days,
                            '总升数': condition['water_number'],
                            '房间人数': params['count'],
                            '总天数':(condition['end_date'] - condition['start_date']).days + 1
                        }]})
            if condition.get('electricity_number'):
                options.append({
                    'order_id': order_id,
                    'recode_id': self.__get_order_recode_id(condition, order_id, '电费'),
                    'start_date': condition['start_date'],
                    'end_date': condition['end_date'],
                    'electricity_number': [
                        '电费',
                        order_id, {
                            '实际发生天数': days,
                            '总度数': condition['electricity_number'],
                            '房间人数': params['count'],
                            '总天数':(condition['end_date'] - condition['start_date']).days + 1
                        }]})
        return options

    def __get_order_recode_id(self, condition, order_id, process_name):
        recode_id = False
        if condition.get('id'):  # 编辑
            _filters = MongoBillFilter()
            _filters.match_bill(C('id') == condition['id'])
            res = self.query(_filters, 'IEC_Hydropower')
            if len(res):
                recode_order_ids = res[0]['recode_order_ids']
                for x in recode_order_ids:
                    if x['order_id'] == order_id and x['type'] == process_name:
                        recode_id = x['recode_id']
        return recode_id

    def jiujiang_update_hydropower(self, data, isImport=False):
        data['start_date'] = string_to_date_only(
            data['start_date'].split('T')[0])
        data['end_date'] = string_to_date_only(data['end_date'].split('T')[0])
        data['operator_id'] = get_current_user_id(self.session)
        hasId = data.get('id')  # 是否新增
        data = get_info(data, self.session)
        flag = OperationType.update.value if hasId else OperationType.add.value
        # 查找该长者订单
        _filter = MongoBillFilter()
        _filter.match_bill(
            (C('user_id') == data['user_id'])
            & (C('state') == CheckInStatus.check_in.value)
        )
        res = self.query(_filter, 'IEC_Check_In')
        if not len(res):
            raise JsonRpc2Error(-36102, '找不到该长者入住订单')
        order_id = res[0]['order_id']
        # 获取生成服务记录的参数
        recode_param = self.accommodation_process.get_item_info('电费', order_id, {
            '实际发生天数': 1,
            '总度数': data['electricity_number'],
            '房间人数': 1,
            '总天数': 1
        })[0]
        recode_param['valuation_amount'] = data['money']
        recode_param.update(
            start_date=data['start_date'], end_date=data['end_date'])
        service_recode = {}
        if hasId:
            _filter_recode = MongoBillFilter()
            _filter_recode.match_bill(C('id') == data['id'])
            res_cost = self.query(_filter_recode, 'IEC_Hydropower_Special')
            if len(res_cost):
                recode_id = res_cost[0]['recode_id']
                service_recode = self.service_operation_func.add_service_record(
                    order_id, recode_param['service_product_id'], '0', other=recode_param, is_update=recode_id)
        else:
            service_recode = self.service_operation_func.add_service_record(
                order_id, recode_param['service_product_id'], '0', other=recode_param)
            data.update(recode_id=service_recode['id'])
        service_recode.update(
            status=RecordStatus.service_completed.value, servicer_id=data['operator_id'])
        if isImport:
            return {'data': data, 'service_recode': service_recode}
        else:
            bill_id = self.bill_manage_server.add_bill(flag, TypeId.hydropower.value, [
                                                       [data], [service_recode]], ['IEC_Hydropower_Special', 'PT_Service_Record'])
            return operation_result(bill_id)

    def get_jiujiang_hydropower_list(self, org_list, condition, page, count):
        if 'start_date' in list(condition.keys()):
            condition['start_date_s'] = condition['start_date'][0]
            condition['end_date_s'] = condition['start_date'][1]
        if 'end_date' in list(condition.keys()):
            condition['start_date_e'] = condition['end_date'][0]
            condition['end_date_e'] = condition['end_date'][1]
        keys = ['id', 'hotel_id', 'start_date_s',
                'end_date_s', 'start_date_e', 'end_date_e']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.inner_join_bill('PT_User', 'user_id', 'id', 'user') \
               .match_bill(
            (C('id') == values['id'])
            & (C('start_date') >= as_date(values['start_date_s']))
            & (C('start_date') <= as_date(values['end_date_s']))
            & (C('end_date') >= as_date(values['start_date_e']))
            & (C('end_date') <= as_date(values['end_date_e']))
            & (C('hotel_id') == values['hotel_id'])
            & (C('organization_id').inner(org_list)))\
            .sort({'modify_date': -1})\
            .project({'_id': 0, 'user._id': 0})
        res = self.page_query(_filter, 'IEC_Hydropower_Special', page, count)
        return res

    def delete_jiujiang_hydropower(self, ids, table_name):
        bill_id = False
        for service_scope_id in ids:
            # 查询被删除的数据信息
            _filter = MongoBillFilter()
            _filter.match_bill(C('id') == service_scope_id) \
                .inner_join_bill('PT_Service_Record', 'recode_id', 'id', 'recode') \
                .match(C('recode.cost_status') == None)
            res = self.query(_filter, table_name)
            if len(res):
                bill_id = self.bill_manage_server.add_bill(OperationType.delete.value,
                                                           TypeId.serviceProduct.value, [[{'id': res[0]['id']}], [{'id': res[0]['recode_id']}]], [table_name, 'PT_Service_Record'])
            else:
                raise JsonRpc2Error(-36105, '该费用已生成账单或不存在,不能删除')
        return operation_result(bill_id)

    def upload_hydropower(self, data):
        pf = pd.DataFrame(data)
        pf.rename(columns={'长者': 'name', '身份证': 'id_card', '开始时间': 'start_date', '结束时间': 'end_date',
                           '费用': 'money', '用电量': 'electricity_number', '备注': 'remark'}, inplace=True)
        id_cards = pf['id_card'].values.tolist()
        _filter = MongoBillFilter()
        _filter.match_bill(C('id_card').inner(id_cards)) \
               .project({'id': 1, 'name': 1, 'id_card': 1, '_id': 0})
        res = self.query(_filter, 'PT_User')
        user_pf = pd.DataFrame(res)
        new_pf = pd.merge(pf, user_pf, on=['name', 'id_card'])
        new_pf.rename(columns={'id': 'user_id'}, inplace=True)
        if len(new_pf.index) != len(pf.index):
            raise JsonRpc2Error(-36101, '长者信息有误，请仔细检查')
        new_pf = new_pf.drop(['id_card'], axis=1)
        condition = dataframe_to_list(new_pf)
        recode = []
        data_new = []
        for i, x in enumerate(condition):
            cur_name = x['name']
            del x['name']
            if (x['start_date'] and x['end_date']):
                try:
                    parms = self.jiujiang_update_hydropower(x, True)
                    recode.append(parms['service_recode'])
                    data_new.append(parms['data'])
                except:
                    raise JsonRpc2Error(-36105, '找不到' +
                                        cur_name+'的入住订单或者开始/结束时间已存在')
            else:
                raise JsonRpc2Error(-36102, '请确保开始时间和结束时间填写完整')
        bill_id = self.bill_manage_server.add_bill(OperationType.add.value, TypeId.hydropower.value, [
                                                   data_new, recode], ['IEC_Hydropower_Special', 'PT_Service_Record'])
        return '导入成功' if bill_id else '导入失败'

    def export_template(self, org_list):
        _filter = MongoBillFilter()
        _filter.match_bill(
            (C('organization_id').inner(org_list))
            & (C('state') == '居住中'))\
            .inner_join_bill('PT_User', 'user_id', 'id', 'user')\
            .add_fields({
                '身份证': '$user.id_card',
                '长者': '$user.name',
                '开始时间': '',
                '结束时间': '',
                '费用': '',
                '用电量': '',
                '备注': ''

            })\
            .project({'_id': 0, '长者': 1, '身份证': 1, '开始时间': 1, '结束时间': 1, '费用': 1, '用电量': 1, '备注': 1, })
        res = self.query(_filter, 'IEC_Check_In')
        return res
